/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package client;

import java.io.*;
import java.net.*;
import Common.Message;

/**
 * ClientNetwork class is created to manage network communication between
 * client and server. This class is used only used to send message and not to
 * receive any data. This class create a ClientThread to receive data from server.
 *
 * @author hartingm
 */
public class ClientNetwork {
	/********************
	 * Attributes
	 ********************/
	private Socket transfertSocket;
	private ProjetChatView projetChatView;
	private ClientThread clientThread;
	private String nickname;
    private ConnectView connectView;
	private OutputStream outputStream;
    private DataOutputStream dataOutputStream;

	/**
	 * Build a new ClientNetwork. This method open a new socket and create a ClientThread.
	 *
     * @param projetChatView the project chat view which created this class
     * @param connectView the connectView that initiated the connection procedure
     * @param serverName the name of server to connect
     * @param remotePort the listening port of server
	 * @param nickname the nickname of client
	 * @throws Exception any exception that could occur during the constructor execution
     */
	public ClientNetwork(ProjetChatView projetChatView, ConnectView connectView, String serverName, int remotePort, String nickname) throws Exception {
			this.nickname = nickname;
			this.projetChatView = projetChatView;
            this.connectView = connectView;
			
			System.out.println("Client: Creating transfertSocket");
			this.transfertSocket = new Socket(serverName, remotePort);
			System.out.println("Client: connected to "+transfertSocket.getInetAddress()+":"+transfertSocket.getPort());

			this.outputStream = transfertSocket.getOutputStream();
            this.dataOutputStream = new DataOutputStream(outputStream);

			System.out.println("Client: Creating ClientThread.");
			this.clientThread = new ClientThread("Client Thread", this, projetChatView, connectView, transfertSocket);
			
			System.out.println("Client: Sending connection message.");
			Message connectionMessage = new Message(Message.CONNECTION, nickname, "none", "none");
			sendMessage(connectionMessage);
            projetChatView.setConnected(true);
            projetChatView.setStatus("Connected.");
	}

	/**
	 * Getter for clientThread attribute.
	 * @return the client thread created by this instance of ClientNetwork
	 */
	public ClientThread getClientThread() {
		return clientThread;
	}//end get ClientThread

	/**
	 * This class send a message to server.
	 *
	 * @param message the message to send
	 */
	public synchronized void sendMessage(Message message) {
                try {
                    dataOutputStream.write(message.getType());
                    dataOutputStream.writeUTF(message.getNickSrc());
                    dataOutputStream.writeUTF(message.getNickDest());
                    dataOutputStream.writeUTF(message.getMessage());
                    
                    System.out.println("Client: Message sent.");
                }
                catch(Exception e){
					System.out.println("Client: ERROR class ClientNetwork method sendMessage ("+e.toString()+").");
                }
        }//end sendMessage

	/**
	 * Send a file to an other client.
	 *
	 * @param fileToSend the file
	 * @param nickDest the recipient
	 */
	public void sendFile(File fileToSend, String nickDest) {
		if (fileToSend.exists()) {
			try {
				FileInputStream fileIn = new FileInputStream(fileToSend);
				byte[] buffer = new byte[1024];
				int length;
				boolean fileSent = false;

				while (!fileSent) {
					length = fileIn.read(buffer);
					if (length != -1) {
						synchronized(this) {//synchronized part
							dataOutputStream.write(Message.FILE);
							dataOutputStream.writeUTF(nickname);
							dataOutputStream.writeUTF(nickDest);
							dataOutputStream.writeInt(length);
							dataOutputStream.write(buffer);
						}
						Thread.sleep(100);
					}
					else {
						fileSent = true;
						Message endFileMessage = new Message(Message.FILE_END, nickname, nickDest, "none");
						sendMessage(endFileMessage);
                        clientThread.setIsSendingFile(false);
                        clientThread.setFileToSend(null);
                        clientThread.setNickDest(null);
						System.out.println("Client: File sent");
                        projetChatView.userMessage("Transfert success !", "The file has been transfered.");
						projetChatView.setProgressBarInderterminate(false);
						projetChatView.setProgressBarVisible(false);
						projetChatView.setStatus("Connected");
					}
				}	
			}
			catch(Exception e) {
				System.out.println("Client: ERROR while sending file "+e.toString());
				clientThread.setIsSendingFile(false);
				clientThread.setFileToSend(null);
				clientThread.setNickDest(null);
			}
		}
		else {
			System.out.println("Client: File doesn't exist -> ERROR.");
            clientThread.setIsSendingFile(false);
            clientThread.setFileToSend(null);
            clientThread.setNickDest(null);
		}
	}//end sendFile
	
	/**
	 * This method close the connection between client and server.
	 * If sendMessage is true then a disconnection message is sent to server.
	 *
	 * @param sendMessage If true, a disconnection message is sent
	 */
	public void disconnect(boolean sendMessage) {
		try {
			System.out.println("Client: Stopping ClientThread.");
			clientThread.stopClientThread();
			
			if (sendMessage == true) {
				System.out.println("Client: Sending disconnection message.");
				Message disconnectionMessage = new Message(Message.DISCONNECTION, nickname, "none", "none");
				sendMessage(disconnectionMessage);
				Thread.sleep(100);
			}
			
			System.out.println("Client: Closing transfert socket.");
			transfertSocket.close();
		}
		catch(Exception e) {
			System.out.println("Client: ERROR class ClientNetwork method disconnect ("+e.toString()+").");
		}
	}//end disconnect
	
};//end ClientNetwork
